import * as T from '@amap/amap-jsapi-loader'

import { data1, data2, data3 } from '../mock'
import { MapContainer, MapOptions, PolygonStyle, ConstructDistrictExplorer, Point } from '../types'

const AMapLoader = T as any

/**
 * @param dom 容器
 * @param mapOptions 地图配置参数
 * @param adcode 行政区码
 * @param isShowDistrict 是否展示行政区规划
 * @returns
 */
export function useAMap(
  dom: MapContainer,
  mapOptions: MapOptions | undefined,
  adcode: number | undefined,
  isShowDistrict: boolean
) {
  const map = shallowRef<any>(null) // 地图对象
  // loca实例
  // 注意: 当使用loca构造3d效果区划时,如果同时有加入其他的图层,像scatterLayer,linkLayer等,
  // 需保证区划加载完成后,再向loca添加,这里使用了awiat保证业务功能在区划加载完成后调用
  const loca = shallowRef<any>(null)
  const districtExplorer = shallowRef<any>(null) // 行政区划实例
  const polygonLayer = shallowRef<any>(null) // 区划图层实例

  // 业务层数据
  const markers = shallowRef<any>(null) // 落点标记
  const heatMapLayer = shallowRef<any>(null) // 热力图层

  const initAMap = async (isReload: boolean) => {
    return new Promise((resolve, reject) => {
      if (window?.AMap) {
        // AMapLoader.reset()
        // 当已加载过其他高德js api时，且key值不同，
        // 重置AMapLoader的状态（调用后会删除已加载的AMap、AMapUI和Loca），
        // 避免加载混用多个版本 JS API 的错误用法高德给予报错处理
        if (isReload) {
          AMapLoader.reset()
        } else {
          resolve('全局已加载高德api！')
        }
      }

      window._AMapSecurityConfig = { securityJsCode: '0e732b0e1fd753335e3607fdfa43a195' } // 自2021年12月02日高德api升级，升级之后所申请的key需配合安全密钥jscode一起使用
      AMapLoader.load({
        key: 'f857cf1eaeb2c24365167da69c5ef311',
        version: '2.0', // 指定要加载的 JSAPI 的版本，缺省时默认为 1.4.15
        AMapUI: {
          // 是否加载 AMapUI，缺省不加载
          version: '1.1' // AMapUI 版本
        },
        Loca: {
          // 是否加载 Loca， 缺省不加载
          version: '2.0' // Loca 版本
        },
        plugins: ['AMap.DistrictLayer', 'AMap.Geocoder', 'AMap.DistrictSearch', 'AMap.Marker'] // 需要使用的的插件列表
      })
        .then(async (AMap: any) => {
          map.value = new AMap.Map(dom, mapOptions || {})

          loca.value = new window.Loca.Container({
            map: map.value
          })

          if (isShowDistrict) {
            await createDistrictExplorer()
            await loadAreaNode()
          }

          resolve('高德api加载成功！')
        })
        .catch((error: any) => {
          reject(error)
        })
    })
  }

  const createDistrictExplorer = () => {
    return new Promise((resove) => {
      window.AMapUI.loadUI(['geo/DistrictExplorer'], function (DistrictExplorer: any) {
        districtExplorer.value = new DistrictExplorer({
          eventSupport: true,
          map: map.value
        } as ConstructDistrictExplorer)
        resove('AMapUI加载成功！')
      })
    })
  }

  /**
   * @param clickCode 下钻或点击面包屑选中的行政区码
   */
  const loadAreaNode = (clickCode?: number | null) => {
    return new Promise((resolve) => {
      districtExplorer.value.loadAreaNode(
        clickCode || adcode,
        function (error: any, areaNode: any) {
          if (error) {
            console.error(error)
            return
          }

          // 位置识别
          districtExplorer.value.setAreaNodesForLocating([areaNode])

          //绘制载入的区划节点
          renderAreaNode(areaNode)

          // 绘制loca图层，伪造立体效果
          createPolygonLayer(areaNode)

          resolve('区域加载器加载完成!')
        }
      )
    })
  }

  const renderAreaNode = (areaNode: any) => {
    //清除已有的绘制内容
    districtExplorer.value.clearFeaturePolygons()

    //just some colors
    const colors = [
      '#3366cc',
      '#dc3912',
      '#ff9900',
      '#109618',
      '#990099',
      '#0099c6',
      '#dd4477',
      '#66aa00'
    ]

    //绘制子级区划
    districtExplorer.value.renderSubFeatures(areaNode, function (feature: any, i: number) {
      const fillColor = colors[i % colors.length]
      const strokeColor = colors[colors.length - 1 - (i % colors.length)]

      return {
        cursor: 'pointer',
        bubble: true,
        strokeColor: strokeColor, //线颜色
        strokeOpacity: 0, //线透明度
        strokeWeight: 1, //线宽
        fillColor: fillColor, //填充色
        fillOpacity: 0 //填充透明度
      }
    })

    //绘制父级区划，仅用黑色描边
    districtExplorer.value.renderParentFeature(areaNode, {
      cursor: 'default',
      bubble: true,
      strokeColor: 'black', //线颜色
      fillColor: 'null',
      strokeWeight: 0 //线宽
    })

    //更新地图视野以适合区划面
    map.value.setFitView(districtExplorer.value.getAllFeaturePolygons())
  }

  const createPolygonLayerData = (areaNode: any) => {
    return {
      type: 'FeatureCollection',
      features: [areaNode._data.geoData.lngLatParent]
    }
  }

  const createPolygonLayer = (areaNode: any) => {
    // 下钻或者点击面包屑时，清除已有的图层
    if (loca.value) {
      loca.value.clear()
    }

    polygonLayer.value = new window.Loca.PolygonLayer({
      loca: loca.value,
      zIndex: 9,
      opacity: 0.8,
      shininess: 10,
      hasSide: true
    })
    const data = createPolygonLayerData(areaNode)
    const geoSource = new window.Loca.GeoJSONSource({
      data
    })
    polygonLayer.value.setSource(geoSource)

    // 设置立体样式
    const polygonStyles = {
      topColor: (index: number, feature: any) => {
        return 'rgba(0, 0, 0, 0)'
      },
      sideTopColor: 'green',
      bottomColor: 'yellow',
      sideBottomColor: 'blue',
      altitude: -50000,
      height: 50000
    } as PolygonStyle
    polygonLayer.value.setStyle(polygonStyles)
  }

  /**
   *
   * @param area 掩膜区域
   * @param isSatellite 是否添加卫星图
   */
  const creatMask = (area: string, isSatellite = false) => {
    const opts = {
      subdistrict: 0,
      extensions: 'all',
      level: 'city'
    }
    //利用行政区查询获取边界构建mask路径
    //也可以直接通过经纬度构建mask路径
    const district = new window.AMap.DistrictSearch(opts)
    district.search(area, async function (status: any, result: any) {
      console.log(result, area, status)
      const bounds = result.districtList[0].boundaries
      const mask = []
      for (let i = 0; i < bounds.length; i += 1) {
        mask.push([bounds[i]])
      }
      map.value.setMask(mask)
      isSatellite && map.value.addLayer(new window.AMap.TileLayer.Satellite())
    })
  }

  // #region 以下为业务功能示例 ！！！！！！！！！！！！！！！！！！！

  // 业务落点示例,可结合具体需求进行改造
  const createMarker = (pointList: Array<Point>) => {
    if (markers.value && markers.value?.length) {
      map.value.remove(markers.value)
      markers.value = null
    }

    if (!pointList.length) return

    markers.value = pointList.map((k) => {
      const item = new window.AMap.Marker({
        map: map.value,
        position: k.lnglat
      })
      return item
    })
  }

  // 业务热力图示例,可结合具体需求进行改造
  const createHeatMap = (pointList: Array<Point & { count: number }>) => {
    let maxCount = 0
    const geoHeat = new window.Loca.GeoJSONSource({
      data: {
        type: 'FeatureCollection',
        features: pointList.map((item) => {
          maxCount = Math.max(maxCount, item.count)
          return {
            type: 'Feature',
            properties: {
              count: item.count
            },
            geometry: {
              type: 'Point',
              coordinates: item.lnglat
            }
          }
        })
      }
    })

    // 热力图
    heatMapLayer.value = new window.Loca.HeatMapLayer({
      zooms: [2, 20],
      zIndex: 20000,
      visible: true,
      opacity: 1
    })

    heatMapLayer.value.setSource(geoHeat, {
      radius: 15,
      unit: 'px',
      height: 20,
      gradient: {
        0: '#87cff8',
        0.2: '#33ac34',
        0.3: '#ecdc4f',
        0.4: '#ff6204',
        0.6: '#ef3909',
        0.85: '#df2b11',
        0.95: '#d62316',
        1: '#c4141f'
      },
      value: function (_index: any, feature: { properties: { count: any } }) {
        return feature.properties.count
      },
      min: 0,
      max: maxCount,
      heightBezier: [0, 0.53, 0.37, 0.98]
    })
    loca.value.add(heatMapLayer.value)
  }

  // 业务飞线图示例,可结合具体需求进行改造
  const creatFlyLine = () => {
    // 文字图层
    const labelLayer = new window.AMap.LabelsLayer({
      rejectMapMask: true,
      collision: true,
      animation: true
    })
    map.value.add(labelLayer)

    const linkLayer = new window.Loca.LinkLayer({
      zIndex: 20,
      opacity: 1,
      visible: true,
      zooms: [2, 22]
    })

    const scatterLayer1 = new window.Loca.ScatterLayer({
      zIndex: 10,
      opacity: 1,
      visible: true,
      zooms: [2, 22]
    })
    const scatterLayer2 = new window.Loca.ScatterLayer({
      zIndex: 10,
      opacity: 0.8,
      visible: true,
      zooms: [2, 22]
    })
    const scatterLayer3 = new window.Loca.ScatterLayer({
      zIndex: 10,
      opacity: 0.8,
      visible: true,
      zooms: [2, 22]
    })

    const centerPoint = new window.Loca.GeoJSONSource({
      data: {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: [116.39, 39.9]
            }
          }
        ]
      }
    })

    scatterLayer3.setSource(centerPoint)
    scatterLayer3.setStyle({
      size: [300000, 300000],
      unit: 'meter',
      altitude: 50000,
      texture: 'https://a.amap.com/Loca/static/static/center-point.png'
    })
    loca.value.add(scatterLayer3)

    let lineGeoMap: any = undefined
    let scatterGeoMap: any = undefined

    const filterGeoJSON = (json: any, type: any) => {
      const newJSON = {
        type: 'FeatureCollection',
        features: [...json.features.filter((item) => item.properties.type === type)]
      }
      return new window.Loca.GeoJSONSource({
        data: newJSON
      })
    }

    const setLabelsLayer = (data: any) => {
      labelLayer.clear()
      data.features.forEach((item: any) => {
        const labelsMarker = new window.AMap.LabelMarker({
          name: item.properties.flagName,
          position: item.geometry.coordinates,
          zooms: [2, 22],
          opacity: 1,
          zIndex: 10,
          text: {
            content: item.properties.country,
            direction: 'bottom',
            offset: [0, -5],
            style: {
              fontSize: 13,
              fontWeight: 'normal',
              fillColor: '#fff'
            }
          }
        })
        labelLayer.add(labelsMarker)
      })
      labelLayer.add(
        new window.AMap.LabelMarker({
          name: 'china',
          position: [116.39, 39.9],
          zooms: [2, 22],
          opacity: 1,
          zIndex: 10,
          rank: 100,
          text: {
            content: '中国',
            direction: 'bottom',
            offset: [0, -5],
            style: {
              fontSize: 13,
              fontWeight: 'normal',
              fillColor: '#fff'
            }
          }
        })
      )
    }


    // 脉冲线图
    // 颜色配置
    const headColors = [
      '#ECFFB1',
      '#146968',
      '#146968',
      '#146968',
      '#146968',
      '#146968',
      '#146968',
      '#146968'
    ]
    const trailColors = [
      'rgba(255,178,6, 0.2)',
      'rgba(255,178,6, 0.2)',
      'rgba(20,105,104, 0.2)',
      'rgba(20,105,104, 0.2)',
      'rgba(20,105,104, 0.2)',
      'rgba(20,105,104, 0.2)',
      'rgba(20,105,104, 0.2)',
      'rgba(20,105,104, 0.2)'
    ]
    const layer = new window.Loca.PulseLineLayer({
      zIndex: 11,
      opacity: 1,
      visible: true,
      zooms: [2, 22]
    })
    const pluseData = new window.Loca.GeoJSONSource({
      data: data3
    })
    layer.setSource(pluseData)
    layer.setStyle({
      altitude: 0,
      lineWidth: (_, feature) => feature.properties.lineWidthRatio * 1 + 3,
      headColor: (_, feature) => headColors[feature.properties.type],
      trailColor: (_, feature) => trailColors[feature.properties.type],
      interval: 0.25,
      duration: 5000
    })
    loca.value.add(layer)

    // 添加飞线
    // 创建数据
    lineGeoMap = Object.entries(data2).reduce((accu, curr) => {
      const [key, geo] = curr
      accu[key] = new window.Loca.GeoJSONSource({
        data: geo
      })
      return accu
    }, {})
    console.log(lineGeoMap, Object.entries(data2))

    linkLayer.setSource(lineGeoMap[50])
    linkLayer.setStyle({
      lineColors: function (index, item) {
        return item.link.properties.type === 0 ? ['#25CDEA', '#12BFBF'] : ['#FFD87B', '#FF4F00']
      },
      height: function (index, item) {
        return item.distance / 3
      },
      smoothSteps: function (index, item) {
        return 200
      }
    })
    // loca.value.add(linkLayer)

    // 添加贴地点
    scatterGeoMap = data1
    setLabelsLayer(scatterGeoMap[50])
    const source1 = filterGeoJSON(scatterGeoMap[50], 0)
    const source2 = filterGeoJSON(scatterGeoMap[50], 1)
    scatterLayer1.setSource(source1)
    scatterLayer2.setSource(source2)
    scatterLayer1.setStyle({
      size: [500000, 500000],
      unit: 'meter',
      animate: true,
      duration: 1000,
      texture: 'https://a.amap.com/Loca/static/static/green.png'
    })
    scatterLayer2.setStyle({
      size: [500000, 500000],
      unit: 'meter',
      animate: true,
      duration: 1000,
      texture: 'https://a.amap.com/Loca/static/static/orange.png'
    })
    loca.value.add(scatterLayer1)
    loca.value.add(scatterLayer2)
    loca.value.animate.start()
  }

  // #endregion 以上为业务功能示例 ！！！！！！！！！！！！！！！！！！！

  onBeforeUnmount(() => {
    if (loca.value) {
      loca.value.clear()
      loca.value.destory()
    }
    if (map.value) {
      map.value.clear()
      map.value.destory()
    }

    map.value = null
    loca.value = null
    districtExplorer.value = null
    polygonLayer.value = null
  })

  return {
    map,
    loca,
    districtExplorer,
    polygonLayer,
    initAMap,
    loadAreaNode,
    creatMask,
    createMarker,
    createHeatMap,
    creatFlyLine
  }
}
